#ifndef SANITIZER_REPORT_H
#define SANITIZER_REPORT_H

#include "asan_internal_defs.h"
#include "asan_signal_handler.h"

namespace __sanitizer {

#define GET_CALLER_PC_BP         \
  uptr bp = GET_CURRENT_FRAME(); \
  uptr pc = GET_CALLER_PC();

#define GET_CALLER_PC_BP_SP \
  GET_CALLER_PC_BP;         \
  uptr local_stack;         \
  uptr sp = (uptr)&local_stack

#define ASAN_REPORT_ERROR(type, is_write, size)                                        \
  extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_report_##type##size(uptr addr) { \
    GET_CALLER_PC_BP_SP;                                                               \
    ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true);                     \
  }

#define ASAN_REPORT_ERROR_N(type, is_write)                                                     \
  extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_report_##type##_n(uptr addr, uptr size) { \
    GET_CALLER_PC_BP_SP;                                                                        \
    ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true);                              \
  }

void PrintShadowErrorTable(uptr addr);

void ReportStackTrace();

void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
                        uptr access_size, u32 exp, bool fatal);
void ReportDoubleFree(uptr pc, uptr bp, uptr sp, uptr addr);
void ReportFreeNotMalloced(uptr pc, uptr bp, uptr sp, uptr addr);

void CheckAndReport(const void* membeg, uptr size, bool is_write);

void ReportErrorInfo(uptr pc, uptr bp, uptr sp, uptr addr, const char* behavior,
                     uptr access_size);

void ReportCapturedDeadlySignal(int signal, uptr pc, uptr bp, uptr sp, SignalContext sc);

} // namespace __sanitizer

#endif  // SANITIZER_REPORT_H